item11-在operator=中处理自我赋值

现实中,存在潜在的自我赋值:

a[i] = a[j];	//i == j时,自我赋值
*px  = *py;		//px == py是,自我赋值

自定义类型常见的赋值操作符实现:

Widget& operator=(const Widget& rhs) {
    delete ptr;
    ptr = new A(*rhs.ptr);
    return *this;
}

这种写法有两种风险:

  • (*this).ptr 有可能等于rhs.ptr,这样的话,delete ptr时,双方的内容都被释放
  • 如果new时发生异常,但此时(*this).ptr已经被delete

优化:

Widget& operator=(const Widget& rhs) {
    if(this == &rhs)return *this;	//证同测试
    
    A* tmp = ptr;
    ptr = new A(*rhs.ptr);
    delete tmp;		//new 成功后再释放
    return *this;
}

进阶,使用copy and swap技术:

// 写法1,函数参数为引用
Widget& operator=(const Widget& rhs) {
    Widget tmp(rhs);
    swap(tmp);
    return *this;
}
// 写法2,函数参数为值传递,值传递的参数本身就是一份副本
Widget& operator=(Widget rhs) {
    swap(rhs);
    return *this;
}